package com.soft.admin.service.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.soft.admin.common.ElementConst;
import com.soft.admin.dto.ActionDTO;
import com.soft.admin.dto.MenuDetailDTO;
import com.soft.admin.dto.MenuImgDTO;
import com.soft.admin.dto.MenuToDTO;
import com.soft.admin.service.MenuService;
import com.soft.model.Action;
import com.soft.model.ActionColumn;
import com.soft.model.Role;
import com.soft.model.RoleColumn;
import com.soft.util.JsonUtil;

@SuppressWarnings("unchecked")
@Component
public class MenuServiceImpl extends BaseServiceImpl implements MenuService {

	@Transactional(readOnly = true)
	public String get() {
		List<ActionColumn> acs = this.getBaseDao().findAll(ActionColumn.class, new Order[] {Order.asc("leaf")});
		Map<Integer, MenuDetailDTO> menuMaps = new HashMap<Integer, MenuDetailDTO>();
		for (ActionColumn ac : acs) {
			if (menuMaps.containsKey(ac.getId())) continue;
			MenuDetailDTO dto = new MenuDetailDTO();
			dto.setId(ac.getId());
			dto.setText(ac.getName());
			if (ac.getParent() != null){
				dto.setParent(ac.getParent().getId());
			}
			dto.setNamespace(ac.getNamespace());
			dto.setIcon(ElementConst.ICONPATH + ac.getIcon());
			dto.setAleaf(ac.getLeaf());
			menuMaps.put(ac.getId(), dto);
			menuMaps = this.rebuild(menuMaps, dto);
		}
		List<MenuDetailDTO> dtos = new ArrayList<MenuDetailDTO>();
		for (MenuDetailDTO menu : menuMaps.values()) {
			if (menu.getParent() == 0) dtos.add(menu);
		}
		return JsonUtil.toString(dtos);
	}
	
	/**
	 * 递归构建菜单树形.
	 */
	private Map<Integer, MenuDetailDTO> rebuild(Map<Integer, MenuDetailDTO> menuMaps, MenuDetailDTO doo) {
		if (doo.getParent() == 0) return menuMaps;
		MenuDetailDTO dto = menuMaps.get(doo.getParent());
		List<MenuDetailDTO> lst = dto.getChildren();
		for (MenuDetailDTO ls : lst) {
			if (ls.getId() == doo.getId()) {
				lst.remove(ls);
				break;
			}
		}
		lst.add(doo);
		dto.setChildren(lst);
		menuMaps.put(doo.getParent(), dto);
		if (dto.getParent() != 0) {
			menuMaps = this.rebuild(menuMaps, dto);
		}
		return menuMaps;
	}

	@Transactional(readOnly = true)
	public String getDetail(Integer id) {
		Criterion res = Restrictions.eq("parent.id", id);
		if (id == 0) {
			res = Restrictions.isNull("parent");
		}
		List<ActionColumn> acs = this.getBaseDao().findAll(ActionColumn.class, null, res);
		List<MenuToDTO> dtos = new ArrayList<MenuToDTO>();
		for (ActionColumn ac : acs) {
			MenuToDTO dto = new MenuToDTO();
			BeanUtils.copyProperties(ac, dto, new String[]{"action"});
			dto.setIcon(ElementConst.ICONPATH + ac.getIcon());
			if (ac.getAction() != null){
				dto.setAction(ac.getAction().getId());
			}
			dtos.add(dto);
		}
		return JsonUtil.toString(dtos);
	}

	@Transactional(readOnly = true)
	public String getAction() {
//		List<ActionColumn> acs = this.getBaseDao().findAll(ActionColumn.class, null, Restrictions.isNotNull("action"));
//		List<String> codeLst = new ArrayList<String>();
//		for (ActionColumn ac : acs) {
//			codeLst.add(ac.getAction().getCode());
//		}
		List<Action> actions = this.getBaseDao().findAll(Action.class, null
//				, 
//				Restrictions.not(Restrictions.in("code", codeLst))
				);
		List<ActionDTO> dtos = new ArrayList<ActionDTO>();
		for (Action action : actions) {
			ActionDTO dto = new ActionDTO();
			BeanUtils.copyProperties(action, dto);
			dtos.add(dto);
		}
		return JsonUtil.toString(dtos);
	}

	@Transactional(readOnly = true)
	public String getImg(HttpServletRequest request) {
		File file = new File(request.getSession().getServletContext().getRealPath(ElementConst.SOLUTIONICONPATH));
		List<MenuImgDTO> dtos = new ArrayList<MenuImgDTO>();
		for (File f : file.listFiles()) {
			MenuImgDTO dto = new MenuImgDTO();
			dto.setId(f.getName());
			dto.setPath(ElementConst.ICONPATH + f.getName());
			dtos.add(dto);
		}
		return JsonUtil.toString(dtos);
	}

	@Transactional
	public String addOrEdit(MenuToDTO params, Integer parent) {
		ActionColumn ac = null;
		if (params.getId() == null) {
			ac = new ActionColumn();
			ac.setLeaf(0);
			if (parent != 0) {
				ActionColumn acparent = (ActionColumn)this.getBaseDao().get(ActionColumn.class, parent);
				ac.setParent(acparent);
				ac.setLeaf(acparent.getLeaf() + 1);
			}
			
		} else {
			ac = (ActionColumn)this.getBaseDao().get(ActionColumn.class, params.getId());
		}
		if (params.getAction() != null) {
			Action action = (Action)this.getBaseDao().get(Action.class, params.getAction());
			ac.setAction(action);
		}
		ac.setIcon(this.getIconName(params.getIcon()));
		ac.setLevel(params.getLevel());
		ac.setName(params.getName());
		ac.setNamespace(params.getNamespace());
		this.getBaseDao().save(ac);
		if (params.getId() == null && ac.getLeaf() >= 2) {
			Role role = (Role)this.getBaseDao().findUniqueByProperty(Role.class, "level", 1);
			RoleColumn rc = new RoleColumn();
			rc.setColumn(ac);
			rc.setRole(role);
			this.getBaseDao().save(rc);
			//role.getActionColumns().add(ac);
			//this.getBaseDao().save(role);
		}
		Map<String, Object> res = new HashMap<String, Object>();
		res.put("id", ac.getId());
		return JsonUtil.toRes("保存成功！", res);
	}
	
	@Transactional
	public String remove(Integer id) {
		ActionColumn ac = (ActionColumn)this.getBaseDao().get(ActionColumn.class, id);
		this.removeDetail(ac);
		return JsonUtil.toRes("删除成功！");
	}
	
	private void removeDetail(ActionColumn ac) {
		List<ActionColumn> acs = this.getBaseDao().findAll(ActionColumn.class, null, 
				Restrictions.eq("parent.id", ac.getId()));
		for (ActionColumn acl : acs) {
			removeDetail(acl);
		}
		this.getBaseDao().delete(ac);
	}
	
	private String getIconName(String path) {
		return path.substring(path.lastIndexOf("/") + 1);
	}
	
}
